#include <iostream>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>

#include <iostream>

using namespace std;
using boost::asio::ip::tcp;

class chat_client
{
public:
  chat_client(boost::asio::io_service& io_service,
      tcp::resolver::iterator endpoint_iterator)
    : io_service_(io_service),
      socket_(io_service)
  {
    boost::asio::async_connect(socket_, endpoint_iterator,
        boost::bind(&chat_client::handle_connect, this,
          boost::asio::placeholders::error));
  }
  
  void write(const char *buff)
  {
	  io_service_.post(boost::bind(&chat_client::do_write, this, buff));
  }

  void close()
  {
	  io_service_.post(boost::bind(&chat_client::do_close, this));
  }

private:
	void handle_connect(const boost::system::error_code& error)
	{
		if (!error)
		{
			cout << "Connected" << endl;
			boost::asio::async_read(socket_,
			  buffer_,
			  boost::bind(&chat_client::handle_read, this,
				boost::asio::placeholders::error));
		}

	}
	void handle_read(const boost::system::error_code& error)
	{		
		boost::asio::async_read(socket_,
          buffer_,
          boost::bind(&chat_client::handle_read, this,
            boost::asio::placeholders::error));
	}

	void nullf(const boost::system::error_code& error)
	{
		if (!error)
			cout << "Write" << endl;
	}
	void do_write(const char *buff)
	{
		boost::asio::async_write(socket_,
          boost::asio::buffer(buff,
            strlen(buff)),
			boost::bind(&chat_client::nullf, this,
			boost::asio::placeholders::error));
	
	}
	void do_close()
	{
		socket_.close();
	}

  boost::asio::io_service& io_service_;
  tcp::socket socket_;
  boost::asio::streambuf buffer_;
};


int main(int argc, char* argv[])
{
  try
  {
    boost::asio::io_service io_service;

    tcp::resolver resolver(io_service);
    tcp::resolver::query query("127.0.0.1", "123");
    tcp::resolver::iterator iterator = resolver.resolve(query);

    chat_client c(io_service, iterator);

    boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service));

    char line[1024];
    while (std::cin.getline(line, 1023))
    {
      c.write(line);
    }

    c.close();
    t.join();
  }
  catch (std::exception& e)
  {
    std::cerr << "Exception: " << e.what() << "\n";
  }

  return 0;
}
